#ifndef __RISCV_PLIC_H__
#define __RISCV_PLIC_H__

#include "main.h"

#define BASE_ADDR_PLIC  ((uint64_t)0x0000000114000000)

#define PRIORITY_0      ((uint32_t)0x00) // RW [3:0] Priority register 0 (source 1 WDT). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_1      ((uint32_t)0x04) // RW [3:0] Priority register 1 (source 1 GP Timer). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_2      ((uint32_t)0x08) // RW [3:0] Priority register 2 (source 2 Boot SPI). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_3      ((uint32_t)0x0C) // RW [3:0] Priority register 3 (source 3 GP SPI). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_4      ((uint32_t)0x10) // RW [3:0] Priority register 4 (source 4 Mailbox). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_5      ((uint32_t)0x14) // RW [3:0] Priority register 5 (source 5 UART). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_6      ((uint32_t)0x18) // RW [3:0] Priority register 6 (source 6 I2C). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_7      ((uint32_t)0x1C) // RW [3:0] Priority register 7 (source 7 GBE0). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_8      ((uint32_t)0x20) // RW [3:0] Priority register 8 (source 8 GBR1). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_9      ((uint32_t)0x24) // RW [3:0] Priority register 8 (source 8 GBR1). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_10      ((uint32_t)0x28) // RW [3:0] Priority register 9 (source 9 USB0). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_11     ((uint32_t)0x2C) // RW [3:0] Priority register 10 (source 10 USB1). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_12     ((uint32_t)0x30) // RW [3:0] Priority register 11 (source 11 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_13     ((uint32_t)0x34) // RW [3:0] Priority register 12 (source 12 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_14     ((uint32_t)0x38) // RW [3:0] Priority register 13 (source 13 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_15     ((uint32_t)0x3C) // RW [3:0] Priority register 14 (source 14 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_16     ((uint32_t)0x40) // RW [3:0] Priority register 15 (source 15 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_17     ((uint32_t)0x44) // RW [3:0] Priority register 16 (source 16 DDR0). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_18     ((uint32_t)0x48) // RW [3:0] Priority register 17 (source 17 DDR1). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_19     ((uint32_t)0x4C) // RW [3:0] Priority register 18 (source 18 PCIe 00). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_20     ((uint32_t)0x50) // RW [3:0] Priority register 19 (source 19 PCIe 01). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_21     ((uint32_t)0x54) // RW [3:0] Priority register 20 (source 20 PCIe 02). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_22     ((uint32_t)0x58) // RW [3:0] Priority register 21 (source 21 PCIe 03). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_23     ((uint32_t)0x5C) // RW [3:0] Priority register 22 (source 22 PCIe 04). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_24     ((uint32_t)0x60) // RW [3:0] Priority register 23 (source 23 PCIe 05). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_25     ((uint32_t)0x64) // RW [3:0] Priority register 24 (source 24 PCIe 06). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_26     ((uint32_t)0x68) // RW [3:0] Priority register 25 (source 25 PCIe 07). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_27     ((uint32_t)0x6C) // RW [3:0] Priority register 26 (source 26 PCIe 08). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_28     ((uint32_t)0x70) // RW [3:0] Priority register 27 (source 27 PCIe 09). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_29     ((uint32_t)0x74) // RW [3:0] Priority register 28 (source 28 PCIe 10). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_30     ((uint32_t)0x78) // RW [3:0] Priority register 29 (source 29 PCIe 11). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_31     ((uint32_t)0x7C) // RW [3:0] Priority register 30 (source 30 PCIe 12). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_32     ((uint32_t)0x80) // RW [3:0] Priority register 31 (source 31 PCIe 13). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_33     ((uint32_t)0x84) // RW [3:0] Priority register 32 (source 32 PCIe 14). Low four bits is effective, the value is range from 0 to 8.
#define PRIORITY_34     ((uint32_t)0x88) // RW [3:0] Priority register 33 (source 33 PCIe 15). Low four bits is effective, the value is range from 0 to 8.

#define PENDING_0       ((uint32_t)0x1000) // RO [31:0] Interrupt Pending register 0, source 0 - source 31.
#define PENDING_1       ((uint32_t)0x1004) // RO [31:0] Interrupt Pending register 1, source 32 - source 63.

#define IE_LSB          ((uint32_t)0x2000) // RW [31:0] Interrupt Enable register 0 core 0 default 0x00000000
#define IE_MSB          ((uint32_t)0x2004) // RW [31:0] Interrupt Enable register 1 core 0 default 0x00000000

#define EL_LSB          ((uint32_t)0x1FFE80) // RW [31:0] Edge or Level trigger type register 0 , source1 - source 32 default 0x00000000
#define EL_MSB          ((uint32_t)0x1FFE84) // RW [31:0] Edge or Level trigger type register 1, source33 - source 64 default 0x00000000

#define SM_LSB          ((uint32_t)0x1FFF00) // RW [31:0] Speed Mode register 0, source 1 - source 32   default 0x00000000
#define SM_MSB          ((uint32_t)0x1FFF04) // RW [31:0] Speed Mode register 1, source 33 - source 64  default 0x00000000

#define DBG_LSB         ((uint32_t)0x1FFF80) // RW [31:0] Debug Enable register 0. source 1 - source 32 default 0x00000000
#define DBG_MSB         ((uint32_t)0x1FFF84) // RW [31:0] Debug Enable register 1. source 33 - source64 default 0x00000000

#define THRESHOLD_0     ((uint32_t)0x200000) // RW [3:0] Priority threshold for context 0 (source 1 WDT).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_1     ((uint32_t)0x201000) // RW [3:0] Priority threshold for context 1 (source 1 GP Timer).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_2     ((uint32_t)0x202000) // RW [3:0] Priority threshold for context 2 (source 2 Boot SPI).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_3     ((uint32_t)0x203000) // RW [3:0] Priority threshold for context 3 (source 3 GP SPI).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_4     ((uint32_t)0x204000) // RW [3:0] Priority threshold for context 4 (source 4 Mailbox).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_5     ((uint32_t)0x205000) // RW [3:0] Priority threshold for context 5 (source 5 UART).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_6     ((uint32_t)0x206000) // RW [3:0] Priority threshold for context 6 (source 6 I2C).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_7     ((uint32_t)0x207000) // RW [3:0] Priority threshold for context 7 (source 7 GBE0).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_8     ((uint32_t)0x208000) // RW [3:0] Priority threshold for context 8 (source 8 GBR1).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_9     ((uint32_t)0x209000) // RW [3:0] Priority threshold for context 9 (source 9 USB0).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_10    ((uint32_t)0x20A000) // RW [3:0] Priority threshold for context 10 (source 10 USB1). Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_11    ((uint32_t)0x20B000) // RW [3:0] Priority threshold for context 11 (source 11 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_12    ((uint32_t)0x20C000) // RW [3:0] Priority threshold for context 12 (source 12 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_13    ((uint32_t)0x20D000) // RW [3:0] Priority threshold for context 13 (source 13 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_14    ((uint32_t)0x20E000) // RW [3:0] Priority threshold for context 14 (source 14 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_15    ((uint32_t)0x20F000) // RW [3:0] Priority threshold for context 15 (source 15 Rsvd). Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_16    ((uint32_t)0x210000) // RW [3:0] Priority threshold for context 16 (source 16 DDR0).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_17    ((uint32_t)0x211000) // RW [3:0] Priority threshold for context 17 (source 17 DDR1).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_18    ((uint32_t)0x212000) // RW [3:0] Priority threshold for context 18 (source 18 PCIe 00).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_19    ((uint32_t)0x213000) // RW [3:0] Priority threshold for context 19 (source 19 PCIe 01).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_20    ((uint32_t)0x214000) // RW [3:0] Priority threshold for context 20 (source 20 PCIe 02).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_21    ((uint32_t)0x215000) // RW [3:0] Priority threshold for context 21 (source 21 PCIe 03).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_22    ((uint32_t)0x216000) // RW [3:0] Priority threshold for context 22 (source 22 PCIe 04).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_23    ((uint32_t)0x217000) // RW [3:0] Priority threshold for context 23 (source 23 PCIe 05).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_24    ((uint32_t)0x218000) // RW [3:0] Priority threshold for context 24 (source 24 PCIe 06).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_25    ((uint32_t)0x219000) // RW [3:0] Priority threshold for context 25 (source 25 PCIe 07).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_26    ((uint32_t)0x21A000) // RW [3:0] Priority threshold for context 26 (source 26 PCIe 08).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_27    ((uint32_t)0x21B000) // RW [3:0] Priority threshold for context 27 (source 27 PCIe 09).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_28    ((uint32_t)0x21C000) // RW [3:0] Priority threshold for context 28 (source 28 PCIe 10).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_29    ((uint32_t)0x21D000) // RW [3:0] Priority threshold for context 29 (source 29 PCIe 11).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_30    ((uint32_t)0x21E000) // RW [3:0] Priority threshold for context 30 (source 30 PCIe 12).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_31    ((uint32_t)0x21F000) // RW [3:0] Priority threshold for context 31 (source 31 PCIe 13).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_32    ((uint32_t)0x220000) // RW [3:0] Priority threshold for context 32 (source 32 PCIe 14).  Low four bits is effective, the value is range from 0 to 8.
#define THRESHOLD_33    ((uint32_t)0x221000) // RW [3:0] Priority threshold for context 33 (source 33 PCIe 15).  Low four bits is effective, the value is range from 0 to 8.

#define ID_0            ((uint32_t)0x200004) // RW [0] Claim/complete for context 0.

#define PRIORITY_0_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_0))
#define PRIORITY_1_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_1))
#define PRIORITY_2_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_2))
#define PRIORITY_3_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_3))
#define PRIORITY_4_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_4))
#define PRIORITY_5_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_5))
#define PRIORITY_6_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_6))
#define PRIORITY_7_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_7))
#define PRIORITY_8_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_8))
#define PRIORITY_9_REG       (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_9))
#define PRIORITY_10_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_10))
#define PRIORITY_11_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_11))
#define PRIORITY_12_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_12))
#define PRIORITY_13_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_13))
#define PRIORITY_14_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_14))
#define PRIORITY_15_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_15))
#define PRIORITY_16_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_16))
#define PRIORITY_17_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_17))
#define PRIORITY_18_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_18))
#define PRIORITY_19_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_19))
#define PRIORITY_20_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_20))
#define PRIORITY_21_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_21))
#define PRIORITY_22_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_22))
#define PRIORITY_23_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_23))
#define PRIORITY_24_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_24))
#define PRIORITY_25_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_25))
#define PRIORITY_26_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_26))
#define PRIORITY_27_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_27))
#define PRIORITY_28_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_28))
#define PRIORITY_29_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_29))
#define PRIORITY_30_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_30))
#define PRIORITY_31_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_31))
#define PRIORITY_32_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_32))
#define PRIORITY_33_REG      (*(volatile uint32_t *)(BASE_ADDR_PLIC + PRIORITY_33))

#define PENDING_LSB_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + PENDING_0))
#define PENDING_MSB_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + PENDING_1))

#define IE_LSB_REG               (*(volatile uint32_t *)(BASE_ADDR_PLIC + IE_LSB))
#define IE_MSB_REG               (*(volatile uint32_t *)(BASE_ADDR_PLIC + IE_MSB))

#define EL_LSB_REG               (*(volatile uint32_t *)(BASE_ADDR_PLIC + EL_LSB))
#define EL_MSB_REG               (*(volatile uint32_t *)(BASE_ADDR_PLIC + EL_MSB))
                           
#define SM_LSB_REG               (*(volatile uint32_t *)(BASE_ADDR_PLIC + SM_LSB))
#define SM_MSB_REG               (*(volatile uint32_t *)(BASE_ADDR_PLIC + SM_MSB))
                          
#define DBG_LSB_REG              (*(volatile uint32_t *)(BASE_ADDR_PLIC + DBG_LSB))
#define DBG_MSB_REG              (*(volatile uint32_t *)(BASE_ADDR_PLIC + DBG_MSB))

#define THRESHOLD_0_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_0))
#define THRESHOLD_1_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_1))
#define THRESHOLD_2_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_2))
#define THRESHOLD_3_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_3))
#define THRESHOLD_4_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_4))
#define THRESHOLD_5_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_5))
#define THRESHOLD_6_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_6))
#define THRESHOLD_7_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_7))
#define THRESHOLD_8_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_8))
#define THRESHOLD_9_REG          (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_9))
#define THRESHOLD_10_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_10))
#define THRESHOLD_11_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_11))
#define THRESHOLD_12_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_12))
#define THRESHOLD_13_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_13))
#define THRESHOLD_14_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_14))
#define THRESHOLD_15_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_15))
#define THRESHOLD_16_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_16))
#define THRESHOLD_17_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_17))
#define THRESHOLD_18_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_18))
#define THRESHOLD_19_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_19))
#define THRESHOLD_20_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_20))
#define THRESHOLD_21_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_21))
#define THRESHOLD_22_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_22))
#define THRESHOLD_23_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_23))
#define THRESHOLD_24_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_24))
#define THRESHOLD_25_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_25))
#define THRESHOLD_26_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_26))
#define THRESHOLD_27_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_27))
#define THRESHOLD_28_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_28))
#define THRESHOLD_29_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_29))
#define THRESHOLD_30_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_30))
#define THRESHOLD_31_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_31))
#define THRESHOLD_32_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_32))
#define THRESHOLD_33_REG         (*(volatile uint32_t *)(BASE_ADDR_PLIC + THRESHOLD_33))

#define ID_0_REG                 (*(volatile uint32_t *)(BASE_ADDR_PLIC + ID_0))

void interrupt_plic_init(void);

#endif // __RISCV_PLIC_H__
